Avoiding Incorrect Inheritance with Capability-Based Modeling
A common modeling mistake is to define Bird with a Fly() method and then derive Penguin and Ostrich from Bird. Penguins and ostriches are birds biologically but cannot satisfy a behavioral contract that requires flying. This can violate the Liskov Substitution Principle because code expecting any Bird to fly would fail for those subclasses. I would separate common bird identity from capabilities such as flying.
The problem is not that Penguin is not a Bird; it is that Bird has been given an inappropriate behavioral contract.
Separate capabilities from identity when capabilities are not universal.
Interfaces such as IFlyingBird can model optional capabilities.
LSP requires derived types to honor the behavioral expectations of their base abstraction.
Avoid methods that derived classes must implement by throwing NotSupportedException merely to satisfy inheritance.